package com.sxf.auth.login.service;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.hash.Hashing;
import com.sxf.auth.enums.*;
import com.sxf.auth.login.dao.AuthUserMapper;
import com.sxf.auth.login.model.AuthUser;
import com.sxf.auth.login.vo.*;
import com.sxf.biz.customer.dao.CustomerMapper;
import com.sxf.biz.customer.dao.CustomerStaffMapper;
import com.sxf.biz.customer.dao.ProjectMapper;
import com.sxf.biz.customer.dao.SettleMapper;
import com.sxf.biz.customer.vo.ProjectListReq;
import com.sxf.biz.customer.vo.ProjectListRes;
import com.sxf.biz.customer.vo.SubjectsListRes;
import com.sxf.biz.model.Customer;
import com.sxf.biz.model.CustomerStaff;
import com.sxf.biz.model.Settle;
import com.sxf.biz.model.SettleStatus;
import com.sxf.cache.CacheUtil;
import com.sxf.cache.EhcacheElementType;
import com.sxf.common.enums.ErrorCodeEnum;
import com.sxf.common.exceptions.BusinessException;
import com.sxf.core.db.page.Pagination;
import com.sxf.utils.YtUtil;
import org.apache.commons.codec.Charsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @description: TODO
 * @Author Leo
 * @date 2024/3/1623:08
 */
@Service
public class UserService extends ServiceImpl<AuthUserMapper, AuthUser> {

    private static final Logger logger= LoggerFactory.getLogger(UserService.class);

    private static final String DEFAULT_PASSWORD = "Aa123456";

    private static final String mobile_reg="^1[0-9]{10}$";
    @Autowired
    CustomerStaffMapper customerStaffMapper;
    @Autowired
    CustomerMapper customerMapper;

    @Autowired
    AuthUserMapper authUserMapper;

    @Autowired
    SettleMapper settleMapper;

    @Autowired
    CacheUtil cacheUtil;


    /**
     * 添加运营端用户
     * @param addUserReq
     * @return
     */
    public AddUserRes addOpUser(AddOpUserReq addUserReq){
        //1.
        AuthUser user = getOne(new QueryWrapper<AuthUser>().lambda().eq(AuthUser::getAccount, addUserReq.getAccount()));
        if(!Objects.isNull(user)){
            throw new BusinessException("该账号已存在");
        }
        if(!YtUtil.validStrPattern(mobile_reg,addUserReq.getUserMobile())){
            throw new BusinessException("请输入正确的手机号");
        }
        user = saveAuthUser(addUserReq,UserTypeEnum.PLATFORM);

        AddUserRes res = new AddUserRes();
        res.setPkUser(user.getPkUser());
        res.setAccount(user.getAccount());
        res.setUserMobile(user.getUserMobile());
        res.setUserName(user.getUserName());

        return res;
    }

    /**
     * 客户端添加协调员和审核员
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AddUserRes addCoorUser(AddCoordinateApproverReq req){
        if(!YtUtil.validStrPattern(mobile_reg,req.getUserMobile())){
            throw new BusinessException("请输入正确的手机号");
        }
        AuthUser user = getOne(new QueryWrapper<AuthUser>().lambda().eq(AuthUser::getAccount, req.getAccount()));
        if(!Objects.isNull(user)){
            QueryWrapper<CustomerStaff> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(CustomerStaff::getPkUser,user.getPkUser())
                    .eq(CustomerStaff::getPkCustomer,req.getPkCustomer())
                    .last("limit 1");
            Integer count = customerStaffMapper.selectCount(queryWrapper);
            if(count > 0){
                logger.error("账号已存在-{}",req.getAccount());
                throw new BusinessException("该账号已存在");
            }
        }else{
            user = saveAuthUser(req, UserTypeEnum.COORDINATE);
        }

        //插入关系表
        CustomerStaff cs = new CustomerStaff();
        cs.setPkUser(user.getPkUser());
        cs.setStaffType(req.getStaffType());
        cs.setPkCustomer(req.getPkCustomer());
        cs.setSmoName(req.getSmoName());
        cs.setStatus(CommonStatusEnum.VALID.getCode());
        cs.setCreator(req.getUserId());
        cs.setCreatorName(req.getCurName());
        cs.setCreatedTime(new Date());
        customerStaffMapper.insert(cs);

        AddUserRes res = new AddUserRes();
        res.setPkUser(user.getPkUser());
        res.setAccount(user.getAccount());
        res.setUserMobile(user.getUserMobile());
        res.setUserName(user.getUserName());
        return res;
    }

    /**
     * 客户端添加协调员和审核员
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public AddUserRes addCutomerAdmin(AddOpUserReq req){
        AuthUser user = getOne(new QueryWrapper<AuthUser>().lambda().eq(AuthUser::getAccount, req.getAccount()));
        if(!Objects.isNull(user)){
            logger.error("账号已存在-{}",req.getAccount());
            throw new BusinessException(ErrorCodeEnum.USER_EXIST_ERROR);
        }
        if(!YtUtil.validStrPattern(mobile_reg,req.getUserMobile())){
            throw new BusinessException("请输入正确的手机号");
        }
        user = saveAuthUser(req, UserTypeEnum.CUSTOMER);
        AddUserRes res = new AddUserRes();
        res.setPkUser(user.getPkUser());
        res.setAccount(user.getAccount());
        res.setUserMobile(user.getUserMobile());
        res.setUserName(user.getUserName());
        return res;
    }

    /**
     * 手机号是否注册
     * @param req
     * @return
     */
    public ValidUserMobileRes validUserMobile(ValidUserMobileReq req){
        List<AuthUser> list = list(new QueryWrapper<AuthUser>().lambda()
                .eq(AuthUser::getUserMobile, req.getUserMobile())
                .eq(AuthUser::getStatus,UserStatusEnum.VALID.getCode())
                .eq(AuthUser::getUserType, UserTypeEnum.SUBJECTS.getCode()));
        ValidUserMobileRes res = new ValidUserMobileRes();
        res.setExist(list.size() > 0);
        return res;
    }

    public Boolean changePassword(ChangePassWordReq req){
        AuthUser user = getById(req.getUserId());
        if(!YtUtil.sha256(user.getSalt(),req.getOldPassword()).equals(user.getPassword())){
            throw new BusinessException("原密码不正确，请确认后重新输入");
        }
        String newSalt = YtUtil.getSalt();
        user.setSalt(newSalt);
        user.setPassword(YtUtil.sha256(newSalt,req.getNewPassword()));
        user.setModifiedTime(new Date());
        user.setModifier(req.getUserId());
        user.setModifierName(req.getCurName());

        return updateById(user);
    }

    public Boolean resetPassword(ResetPasswordReq req){

        String pwd = Hashing.sha256().newHasher().putString(DEFAULT_PASSWORD, Charsets.UTF_8).hash().toString();

        if(UserTypeEnum.CUSTOMER.getCode().equals(req.getClient())){
            QueryWrapper<Customer> customerQueryWrapper = new QueryWrapper<>();
            customerQueryWrapper.lambda().eq(Customer::getPkAdmin,req.getUserId()).last(" limit 1");
            Customer customer = customerMapper.selectOne(customerQueryWrapper);
            if(Objects.isNull(customer)){
                logger.error("操作人无客户端权限");
                throw new BusinessException("无权重置密码");
            }
            QueryWrapper<CustomerStaff> customerStaffQueryWrapper = new QueryWrapper<>();
            customerStaffQueryWrapper.lambda().eq(CustomerStaff::getPkUser,req.getPkUser())
                    .eq(CustomerStaff::getPkCustomer,customer.getPkCustomer()).last(" limit 1");

            CustomerStaff customerStaff = customerStaffMapper.selectOne(customerStaffQueryWrapper);
            if(Objects.isNull(customerStaff)){
                logger.error("该客户-{}下没有该员工-{}",req.getUserId(),req.getPkUser());
                throw new BusinessException("该账号不存在");
            }

            AuthUser needSetPwdUser = getById(req.getPkUser());
            String salt = YtUtil.getSalt();
            needSetPwdUser.setSalt(salt);
            needSetPwdUser.setPassword(YtUtil.sha256(salt,pwd));
            needSetPwdUser.setModifier(req.getUserId());
            needSetPwdUser.setModifierName(req.getCurName());
            needSetPwdUser.setModifiedTime(new Date());
            updateById(needSetPwdUser);
        }else if(UserTypeEnum.PLATFORM.getCode().equals(req.getClient())){
            AuthUser modifier = getById(req.getUserId());
            if(!UserTypeEnum.PLATFORM.getCode().equals(modifier.getUserType())){
                throw new BusinessException("无权操作");
            }
            AuthUser changedUser = getById(req.getPkUser());
            if(changedUser == null){
                throw new BusinessException(ErrorCodeEnum.USER_NOT_EXIST_ERROR);
            }
            String salt = YtUtil.getSalt();
            changedUser.setSalt(salt);
            changedUser.setPassword(YtUtil.sha256(salt,pwd));
            changedUser.setModifier(req.getUserId());
            changedUser.setModifierName(req.getCurName());
            changedUser.setModifiedTime(new Date());
            updateById(changedUser);
        }
        return true;
    }

    /**
     *
     * @param req
     * @return
     */
    public Boolean updateUserStatus(UpdateUserStatusReq req){
        QueryWrapper<Customer> customerQueryWrapper = new QueryWrapper<>();
        customerQueryWrapper.lambda().eq(Customer::getPkAdmin,req.getUserId()).last("limit 1");
        Customer customer = customerMapper.selectOne(customerQueryWrapper);
        if(Objects.isNull(customer)){
            throw new BusinessException("无权操作");
        }
        QueryWrapper<CustomerStaff> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(CustomerStaff::getPkUser,req.getPkUser()).last("limit 1");
        CustomerStaff customerStaff = customerStaffMapper.selectOne(queryWrapper);
        if(Objects.isNull(customerStaff)){
            throw new BusinessException("该用户不属于该机构");
        }

        AuthUser updateUser = getById(req.getPkUser());
        updateUser.setStatus(req.getStatus());
        updateUser.setModifier(req.getUserId());
        updateUser.setModifierName(req.getCurName());
        updateUser.setModifiedTime(new Date());
        return updateById(updateUser);

    }

    public Pagination<SubjectsUserInfoListRes> getSubjectsList(SubjectsUserInfoListReq req){
        return authUserMapper.getSubjectList(new Pagination<>(req),req);
    }

    public SubjectDetailRes getSubjectsUserInfo(SubjectDetailReq req){
        return authUserMapper.getSubjectDetail(req);
    }

    public Pagination<OpUserListRes> getOpUserList(SubjectsUserInfoListReq req){

        return authUserMapper.getOpUserList(new Pagination<>(req),req);
    }


    public Boolean updateUserInfo(UpdateSubInfoReq req){
        AuthUser user = getById(req.getPkUser());
        if(!UserTypeEnum.SUBJECTS.getCode().equals(user.getUserType())){
            throw new BusinessException("无权更新该用户信息");
        }

        QueryWrapper<AuthUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AuthUser::getIdNo,req.getIdNo())
                .eq(AuthUser::getStatus,CommonStatusEnum.VALID.getCode())
                .ne(AuthUser::getPkUser,req.getUserId());
        int count = count(queryWrapper);
        if(count > 0){
            throw new BusinessException("该身份证号已经被注册");
        }
        user.setUserName(req.getUserName());
        user.setIdNo(req.getIdNo());
        user.setSex(req.getSex());
        user.setModifierName(req.getCurName());
        user.setModifier(req.getUserId());
        user.setModifiedTime(new Date());
        updateById(user);
        return true;
    }

    /**
     * 受试者注销账号
     * @param req
     */
    public Boolean logOff(SubjectsLogOffReq req){

        //是否有未审核完成的结算单
        QueryWrapper<Settle> settleQueryWrapper = new QueryWrapper<>();
        settleQueryWrapper.lambda().eq(Settle::getPkSubjects,req.getUserId())
                .in(Settle::getStatus,new ArrayList<>(){{
                    add(SettleStatusEnum.CHECKING.getCode());
                    add(SettleStatusEnum.APPROVED.getCode());
                }});
        List<Settle> settles = settleMapper.selectList(settleQueryWrapper);
        if(settles != null && settles.size() > 0){
            throw new BusinessException("您还有尚未审批完成的结算单，不能注销当前账户");
        }

        UpdateWrapper<AuthUser> userUpdateWrapper = new UpdateWrapper<>();
        userUpdateWrapper.lambda().set(AuthUser::getStatus,UserStatusEnum.LOGOFF.getCode())
                .set(AuthUser::getModifier,req.getUserId()).set(AuthUser::getModifierName,req.getCurName())
                .set(AuthUser::getModifiedTime,new Date())
                .eq(AuthUser::getPkUser,req.getUserId());
        logger.error("用户-{}注销了该账户",req.getUserId());
        return authUserMapper.update(null,userUpdateWrapper) > 0;
    }

    public Boolean isCoorExist(String userMobile){
        QueryWrapper<AuthUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AuthUser::getUserMobile,userMobile)
                .eq(AuthUser::getUserType,UserTypeEnum.COORDINATE.getCode())
                .eq(AuthUser::getStatus,UserStatusEnum.VALID.getCode());
        Integer count = authUserMapper.selectCount(queryWrapper);
        return count > 0;
    }

    private AuthUser saveAuthUser(AddOpUserReq addUserReq,UserTypeEnum userType) {
        AuthUser user;
        user = new AuthUser();
        String salt = YtUtil.getSalt();
        user.setPkUser(YtUtil.getUuid());
        user.setAccount(addUserReq.getAccount());
        user.setSalt(salt);
        String pwd = Hashing.sha256().newHasher().putString(DEFAULT_PASSWORD, Charsets.UTF_8).hash().toString();
        user.setPassword(YtUtil.sha256(salt,pwd));
        user.setUserName(addUserReq.getUserName());
        user.setUserMobile(addUserReq.getUserMobile());
        user.setUserType(userType.getCode());
        user.setCreator(addUserReq.getUserId());
        user.setCreatorName(addUserReq.getCurName());
        user.setCreatedTime(new Date());
        user.setStatus(UserStatusEnum.VALID.getCode());
        save(user);
        return user;
    }



    public static void main(String[] args) {
        String ss = "123;345;";
        String[] split = ss.split(";");
        System.out.println(split.length);
//        System.out.println(String.format("%04d", 1));
//        System.out.println(DateUtil.format(new Date(),"yy"));
        String pwd = Hashing.sha256().newHasher().putString("Aa123456", Charsets.UTF_8).hash().toString();
        System.out.println(pwd);

        System.out.println(myAtoi("421"));

    }

    public static int myAtoi(String s) {
        if(s == null){
            return 0;
        }
        s = s.trim();
        char flag = '+';
        if(s.charAt(0) =='-' || s.charAt(0) == '+'){
            flag = s.charAt(0);
            s = s.substring(1,s.length());
        }
        int start = 0;
        int res = 0;
        while(start < s.length()){
            if(s.charAt(start) >= '0' && s.charAt(start) <= '9'){
                res = res*10 + Integer.valueOf(String.valueOf(s.charAt(start)));
            }else{
                break;
            }
            start ++;
        }
        if(flag == '-'){
            return -res;
        }else{
            return res;
        }
    }

}
